﻿//=====================================================================================================
// LocalizationLibrary
// The Localization Library is a collection of reusable software components that provide 
// support for localization. This library enables you to localize WPF, Silverlight and WP7 applications.
// (http://localizationlibrary.codeplex.com)
//=====================================================================================================
// Author: Nicola Gallo (Website: www.nicola.gallo.name, Email: nicolagmt@hotmail.it) 
//=====================================================================================================

namespace LocalizationLibrary
{
    //.NET References
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    //LocalizationLibrary References
    using LocalizationLibrary.Attributes;
    using LocalizationLibrary.Reflection;

    /// <summary>
    /// Implements a wrapper class of the class <see cref="LocalizationModel"/>.
    /// </summary>
    public class LocalizationModelRef 
    {
        //Fields

        private WeakReference _weakReference;

        //Constructors

        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="target">Target instance.</param>
        public LocalizationModelRef(Object target)
        {
            this._weakReference = new WeakReference(target);
        }

        //Properties

        /// <summary>
        /// Gets an indication whether the object referenced by the current System.WeakReference
        /// object has been garbage collected.
        /// </summary>
        public bool IsAlive 
        {
            get
            {
                return this._weakReference.IsAlive;
            }
        }

        /// <summary>
        /// Gets an indication whether the object referenced by the current System.WeakReference
        //  object has been garbage collected.
        /// </summary>
        public Object Target
        {
            get 
            {
                return this._weakReference.Target;
            }
            set
            {
                this._weakReference.Target = value;
            }
        }

        //Methods

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>A hash code for the current System.Object</returns>
        public override int GetHashCode()
        {
            int hashCode = 0;
            if (this.IsAlive)
            {
                Object targetInstance = this.Target;
                if (targetInstance != null)
                {
                    hashCode = targetInstance.GetHashCode();   
                }
            }
            return hashCode;
        }

        /// <summary>
        /// Publishes all the new value of properties.
        /// </summary>
        /// <returns>Returns a <see cref="PropertyInfo"/> array whom contains all the properties published.</returns>
        internal PropertyInfoRef[] PublishAllPropertiesValue() 
        {
            LocalizationManager.EnsureCurrentThreadCulture();
            List<PropertyInfoRef> retVal = new List<PropertyInfoRef>(); 
            if (this.IsAlive)
            {
                Object targetInstance = this.Target;
                if (targetInstance != null)
                {
                    PropertyInfoRef[] propertyInfoRefs = AssemblyManager.ReflectionCache.LoadType(targetInstance.GetType()).GetProperties();
                    foreach (PropertyInfoRef propertyInfoRef in propertyInfoRefs)
                    {
                        if (propertyInfoRef.IsLocalized)
                        {
                            Object currentValue = propertyInfoRef.PropertyInfo.GetValue(targetInstance, null);
                            Object localizedValue = propertyInfoRef.Resource.GetLocalizedValue();
                            if (localizedValue != currentValue)
                            {
                                propertyInfoRef.PropertyInfo.SetValue(targetInstance, localizedValue, null);
                                if (typeof(LocalizationModel).IsAssignableFrom(targetInstance.GetType()))
                                {
                                    (targetInstance as LocalizationModel).OnPropertyChange(propertyInfoRef.PropertyInfo.Name);
                                }
                                else if (typeof(INotifyPropertyChanged).IsAssignableFrom(targetInstance.GetType()))
                                {
                                    ((INotifyPropertyChanged)targetInstance).RaiseOnPropertyChangeMethod(propertyInfoRef.PropertyInfo.Name);
                                }
                            }
                            retVal.Add(propertyInfoRef);
                        }
                    }
                }
            }
            return retVal.ToArray();
        }
    }
}